package models

import (
	"github.com/gin-gonic/gin"
	"time"
	"github.com/Unknwon/com"
	"github.com/jinzhu/gorm"
)

type Partner struct {
	ID             int       `gorm:"primary_key" json:"id"`
	Name           string    `json:"name"`
	Phone          string    `json:"phone"`
	UserId         int       `json:"user_id"`
	IdCard         string    `json:"id_card"`
	IdCardImg      string    `json:"id_card_img"`
	BankCardNo     string    `json:"bank_card_no"`
	BankCardName   string    `json:"bank_card_name"`
	BankName       string    `json:"bank_name"`
	BankBranch     string    `json:"bank_branch"`
	PlacePartnerId int       `json:"place_partner_id"`
	OperatorId     int       `json:"operator_id"`
	Status         int       `json:"status"`
	ProvinceId     int       `json:"province_id"`
	CityId         int       `json:"city_id"`
	AreaId         int       `json:"area_id"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

type PartnerByIdResult struct {
	ID             int       `gorm:"primary_key" json:"id"`
	Name           string    `json:"name"`
	Phone          string    `json:"phone"`
	UserId         int       `json:"user_id"`
	IdCard         string    `json:"id_card"`
	IdCardImg      string    `json:"id_card_img"`
	BankCardNo     string    `json:"bank_card_no"`
	BankCardName   string    `json:"bank_card_name"`
	BankName       string    `json:"bank_name"`
	BankBranch     string    `json:"bank_branch"`
	PlacePartnerId int       `json:"place_partner_id"`
	OperatorId     int       `json:"operator_id"`
	Status         int       `json:"status"`
	ProvinceId     int       `json:"province_id"`
	CityId         int       `json:"city_id"`
	AreaId         int       `json:"area_id"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
	IsEnabled      string    `json:"is_enabled"`
	MemberNum      int       `json:"member_num"`
	UsersNum       int       `json:"users_num"`
}

type PartnerArrResult struct {
	Id  int                 `json:"id"`
	Sub []*PartnerArrResult `json:"sub"`
}


func (p *Partner) TableName() string {
	return "salesmen"
}


// 新增
func (a *Partner) AddPartner() (error) {
	var operator Users
	//找到运营商place_partner_id
	operatorErr := DB.Table("users").Select("*").Where("id=?", a.OperatorId).Where("type=?",2).First(&operator).Error
	if operatorErr != nil {
		return operatorErr
	}
	var (
		operator_id      int
		place_partner_id int
	)
	operator_id = a.OperatorId
	place_partner_id = operator.PlacePartnerId
	db := DB.Begin()
	err := db.Model(&Users{}).Where("id=?", a.UserId).Updates(map[string]interface{}{"type": 3, "pid": 0, "operator_id": operator_id, "salesman_id": 0, "place_partner_id": place_partner_id, "account": a.Phone}).Error
	if err != nil {
		db.Rollback()
		return err
	}
	//查找会员下级所有推荐人
	data := GetPartnerRefereeUsersIds(a.UserId)
	//写入进去
	SetPartnerRefereeUsers(operator.PlacePartnerId, a.OperatorId, a.UserId, data, db)
	err1 := db.Table("salesmen").Create(a).Error
	if err1 != nil {
		db.Rollback()
		return err
	}
	db.Commit()
	return nil
}

func DowngradePartner(user_id int) error {
	// 添加虚拟账号
	var user Users
	err := DB.Table("users").Where("id=?", user_id).First(&user).Error
	if err != nil {
		return err
	}
	db := DB.Begin()

	invented := Users{
		Type:               3,
		OperatorId:         user.OperatorId,
		PlacePartnerId:     user.PlacePartnerId,
		IsFaseDistribution: 1,
		CreatedAt:          time.Now(),
	}
	inventedErr := invented.InsertDB(db)
	if inventedErr == false {
		return nil
	}
	// 修改降级会员状态

	err1 := db.Table("users").Where("id=?", user_id).Updates(map[string]interface{}{"type": 4, "salesman_id": invented.ID, "is_change_grade": 1, "account": ""}).Error
	if err1 != nil {
		db.Rollback()
		return err1
	}
	// 修改salesmen对应的user
	err2 := db.Table("salesmen").Where("user_id=?", user.ID).Update("user_id", invented.ID).Error
	if err2 != nil {
		db.Rollback()
		return err2
	}
	UpErr := UpDownPartnerRefereeUsers(invented.ID, user_id, db)
	if err != nil {
		db.Rollback()
		return UpErr
	}
	db.Commit()
	return nil
}

// 查找出所有的下级推荐
func GetPartnerRefereeUsers(user_id int) []*PartnerArrResult {
	var data []*PartnerArrResult
	_ = DB.Table("users").Where("pid=?", user_id).Find(&data).Error
	if data == nil {
		return nil
	}
	var itme []*PartnerArrResult
	for _, v := range data {
		chd := GetPartnerRefereeUsers(v.Id)
		node := &PartnerArrResult{
			Id: v.Id,
		}
		node.Sub = chd
		itme = append(itme, node)
	}
	return itme
}

var arrayId []int
// todo 查找业务员会员下级会员
func GetPartnerRefereeUsersIds(user_id int) []int {
	var data []*PartnerArrResult
	_ = DB.Table("users").Where("pid=?", user_id).Find(&data).Error
	if data == nil {
		return nil
	}

	for _, v := range data {
		arrayId = append(arrayId,v.Id)
		GetPartnerRefereeUsersIds(v.Id)
	}
	return arrayId
}

// 修改下级 对应
func SetPartnerRefereeUsers(place_partner_id int, operator_id int, salesman_id int, data []int, db *gorm.DB) error {
	err := db.Model(&Users{}).Where("id in (?)", data).Updates(map[string]interface{}{"place_partner_id": place_partner_id, "operator_id": operator_id, "salesman_id": salesman_id}).Error
	if err != nil {
		db.Rollback()
		return err
	}
	return nil
}

// 城市合伙人降级 对应
func UpDownPartnerRefereeUsers(salesman_id int, user_id int, db *gorm.DB) error {
	if err := db.Table("users").Where("salesman_id=?", user_id).Update("salesman_id", salesman_id).Error; err != nil {
		db.Rollback()
		return err
	}
	return nil
}

func PartnerList(page int, limit int, c *gin.Context) ([]*PartnerByIdResult, *Paginator) {
	var data []*PartnerByIdResult
	item := DB.Table("users as t1 ").Select("t2.*, t1.is_enabled").Joins("left join salesmen as t2 on t1.id=t2.user_id").Where("t1.is_fase_distribution<>1").Where("t1.type=?", 3).Find(&data)
	if status := c.Query("status"); status != "" {
		item = item.Where("t2.status=?", status)
	}
	if is_enabled := c.Query("is_enabled"); is_enabled != "" {
		item = item.Where("t1.is_enabled=?", is_enabled)
	}
	if province_id := com.StrTo(c.Query("province_id")).MustInt(); province_id != 0 {
		item = item.Where("t2.province_id=?", province_id)
	}

	if begin_time := c.Query("begin_time"); begin_time != "" {
		item = item.Where("t1.created_at >", begin_time)
	}
	if end_time := c.Query("end_time"); end_time != "" {
		item = item.Where("t1.created_at >", end_time)
	}

	if operator_id := com.StrTo(c.Query("operator_id")).MustInt(); operator_id != 0 {
		item = item.Where("t1.operator_id=?", operator_id)

	}
	if phone := c.Query("phone"); phone != "" {
		item = item.Where("t1.phone=?", phone)
	}

	var count int
	item.Count(&count)
	for i := 0; i < len(data); i++ {
		var memberNum int
		var usersNum int
		DB.Table("users as t1").Select("*").Joins("left join user_grade as t2 on t1.id = t2.user_id").Joins("left join vip_fee_config as t3 on t2.vip_fee_config_id=t3.id").Where("t1.salesman_id=?", data[i].UserId).Count(&memberNum)
		DB.Table("users").Select("*").Where("salesman_id=?", data[i].UserId).Count(&usersNum)
		data[i].MemberNum = memberNum
		data[i].UsersNum = usersNum
	}
	paginate := NewPage(page, limit, count)
	return data, &paginate
}

// 获取单个
func (a *PartnerByIdResult) PartnerById() (*PartnerByIdResult, error) {
	var data PartnerByIdResult
	DB.Table("salesmen").Where("id=?", a.ID).First(&data)

	var memberNum int
	var userNum int

	DB.Table("users as t1").Select("*").Joins("left join user_grade as t2 on t1.id = t2.user_id").Joins("left join vip_fee_config as t3").Where("t1.salesman_id=?", data.UserId).Count(&memberNum)
	DB.Table("users").Select("*").Where("salesman_id=?", data.UserId).Count(&userNum)
	data.MemberNum = memberNum
	data.UsersNum = userNum
	return &data, nil
}

func (a *Partner) PartnerEdit() error {
	err := DB.Table("salesmen").Where("id=?", a.ID).Updates(a).Error
	if err != nil {
		return err
	}
	return nil
}

func (a *Partner) PartnerDel() error {
	err := DB.Delete(a, "id=?", a.ID).Error
	if err != nil {
		return err
	}
	return nil
}

func UpdateIsEnabled(user_id int, is_enabled int) error {
	err := DB.Table("users").Where("id=?", user_id).Update("is_enabled", is_enabled).Error
	if err != nil {
		return err
	}
	return nil
}
func ExaminePartner(id int, status string) error {
	err := DB.Table("salesmen").Where("id=?", id).Update("status", status).Error
	if err != nil {
		return err
	}
	return nil
}
func (p *Partner) Recharges(c *gin.Context, page int, limit int) (interface{}, *Paginator){
	var res []*struct{
		ID int `json:"id"`
		UserId int `json:"user_id"`
		AllMoney float64 `json:"all_money"`
		LastMonthMoney float64 `json:"last_month_money"`
		CurrentMoney float64 `json:"current_money"`
		Admin string `json:"admin"`
		Phone string `json:"phone"`
	}
	model := DB.Table("salesmen as p").
		Select("p.id,p.user_id,p.phone,p.name as admin,IFNULL(bonus.money,0) as all_money,IFNULL(bonus_sub.money,0) as last_month_money,IFNULL(bonus_to.money,0) as current_money").
		Joins("left join (select user_id, sum(money) as money from user_salesman_bonus_count where income_type=1 group by user_id) as bonus on bonus.user_id=p.user_id").
		Joins("left join (select user_id, sum(money) as money from user_salesman_bonus_count where income_type=1 and PERIOD_DIFF(date_format(now(), '%Y%m'),date_format(created_at,'%Y%m')) = 1 group by user_id) as bonus_sub on bonus_sub.user_id=p.user_id").
		Joins("left join (select user_id, sum(money) as money from user_salesman_bonus_count where income_type=1 and DATE_FORMAT(created_at,'%Y%m')=DATE_FORMAT(CURDATE(), '%Y%m') group by user_id) as bonus_to on bonus_to.user_id=p.user_id")
	if provinceId := c.Query("province_id"); provinceId != "" {
		model = model.Where("p.province_id=?", provinceId)
	}
	var count int
	model.Count(&count)
	paginate := NewPage(page, limit, count)
	model.Scan(&res)

	return res, &paginate
}

func (p *Partner) RechargesDetail(c *gin.Context, page int, limit int) interface{}  {
	id := c.Query("id")
	var p1 Partner
	DB.Model(p).Where("id=?", id).First(&p1)

	var total float64
	var vipTotal float64
	var vipToday float64
	var eTotal float64
	var newTotal float64
	var lastMonthTotal float64
	var currMonthTotal float64
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("user_id=?", p1.UserId).Where("income_type=1").Row().Scan(&total)
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("income_type=1").Where("user_id=?", p1.UserId).Where("type=1").Row().Scan(&vipTotal)
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("user_id=?", p1.UserId).Where("income_type=1").Where("type=1").Where("to_days(created_at)=to_days(now())").Row().Scan(&vipToday)
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("income_type=1").Where("user_id=?", p1.UserId).Where("type=2").Row().Scan(&newTotal)
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("income_type=1").Where("user_id=?", p1.UserId).Where("type=3").Row().Scan(&eTotal)
	//上月奖励金
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("income_type=1").Where("user_id=?", p1.UserId).Where("PERIOD_DIFF(date_format(now(), '%Y%m'),date_format(created_at,'%Y%m')) = 1").Row().Scan(&lastMonthTotal)
	//当月
	_ = Table("user_salesman_bonus_count").Select("sum(money)").Where("income_type=1").Where("user_id=?", p1.UserId).Where("DATE_FORMAT(created_at,'%Y%m')=DATE_FORMAT(CURDATE(), '%Y%m')").Row().Scan(&currMonthTotal)

	return map[string]float64{
		"total":total,
		"vip_total": vipTotal,
		"e_total" : eTotal,
		"new_total" : newTotal,
		"vip_today": vipToday,
		"last_month_total": lastMonthTotal,
		"curr_month_total": currMonthTotal,
	}
}

func (p *Partner) RechargesVipList(c *gin.Context, page int, limit int) (interface{}, *Paginator)  {
	id := c.Query("id")
	var p1 Partner
	DB.Model(p).Where("id=?", id).First(&p1)
	var res []*struct{
		UserName string	`json:"user_name"`
		Phone string `json:"phone"`
		Relation string `json:"relation"`
		PayTime time.Time `json:"pay_time"`
		VipFeeConfigComment string `json:"vip_level"`
		Money float64 `json:"money"`
		TMoney float64 `json:"t_money"`
		TTime time.Time `json:"t_time"`
	}
	model := Table("user_commission_details as ucd").
		Select("c.user_name,u.phone,ucd.relation,ur.pay_time,ur.vip_fee_config_comment,ur.money,ucd.money as t_money,ucd.created_at as t_time").
		Joins("left join user_recharges as ur on ur.out_trade_no=ucd.out_trade_no").
		Where("ucd.relation_id=?", p1.UserId).
		Joins("left join users u on u.id=ucd.user_id").
		Joins("left join cards c on c.user_id=ucd.user_id")

	if startTime, isExist := c.GetQuery("begin_time"); isExist && startTime != "" {
		model = model.Where("ucd.created_at > ?", startTime)
	}
	if endTime, isExist := c.GetQuery("end_time"); isExist && endTime != "" {
		model = model.Where("ucd.created_at < ?", endTime)
	}
	if phone, isExist := c.GetQuery("phone"); isExist && phone != "" {
		model = model.Where("u.phone=?", phone)
	}
	if vip, isExist := c.GetQuery("vip"); isExist && vip != "" {
		model = model.Where("ur.vip_fee_config_comment=?", vip)
	}

	var count int
	model.Count(&count)
	paginate := NewPage(page, limit, count)
	model.Offset(paginate.Offset).Limit(paginate.Limit).Scan(&res)
	return &res, &paginate
}

func (p *Partner) RechargesNewList(c *gin.Context, page int, limit int) (interface{}, *Paginator)  {
	id := c.Query("id")
	var p1 Partner
	DB.Model(p).Where("id=?", id).First(&p1)

	var res []*struct{
		UserName string `json:"name"`
		Phone string `json:"phone"`
		CreatedAt time.Time `json:"created_at"`
		City string `json:"city"`
		Money float64 `json:"money"`
	}
	model := Table("user_salesman_bonus_count as usbc").Select("c.user_name,u.phone,u.created_at,p.name as city,usbc.money").
		Joins("users u on u.id=usbc.relation_user_id").
		Joins("cards c on c.user_id=usbc.relation_user_id").
		Joins("places p on p.id=c.province").
		Where("usbc.relation_id=?", p1.UserId)

	if startTime, isExist := c.GetQuery("begin_time"); isExist && startTime != "" {
		model = model.Where("usbc.created_at > ?", startTime)
	}
	if endTime, isExist := c.GetQuery("end_time"); isExist && endTime != "" {
		model = model.Where("usbc.created_at < ?", endTime)
	}
	if phone, isExist := c.GetQuery("phone"); isExist && phone != "" {
		model = model.Where("es.phone=?", phone)
	}

	var count int
	model.Count(&count)
	paginate := NewPage(page, limit, count)
	model.Offset(paginate.Offset).Limit(paginate.Limit).Scan(&res)
	return &res, &paginate

}
func (p *Partner) RechargesEList(c *gin.Context, page int, limit int) (interface{}, *Paginator) {
	id := c.Query("id")
	var p1 Partner
	DB.Model(p).Where("id=?", id).First(&p1)
	var res []*struct{
		Name string `json:"name"`
		User string `json:"user"`
		Phone string `json:"phone"`
		Money float64 `json:"money"`
		RMoney float64 `json:"r_money"`
		PayTime time.Time `json:"pay_time"`
	}
	model := Table("user_salesman_bonus_count as usbc").
		Select("e.name,es.name as user,es.phone,er.money,usbc.money as r_money,er.pay_time").
		Joins("left join enterprise_recharge_fenxiao_queue as eq on eq.id=usbc.relation_id").
		Joins("left join enterprise_recharges er on er.out_trade_no=eq.out_trade_no").
		Joins("left join enterprise e on e.id=er.enterprise_id").
		Joins("left join enterprise_staff es on es.id=er.staff_id").
		Where("usbc.user_id=?",p1.UserId)

	if startTime, isExist := c.GetQuery("begin_time"); isExist && startTime != "" {
		model = model.Where("usbc.created_at > ?", startTime)
	}
	if endTime, isExist := c.GetQuery("end_time"); isExist && endTime != "" {
		model = model.Where("usbc.created_at < ?", endTime)
	}
	if phone, isExist := c.GetQuery("phone"); isExist && phone != "" {
		model = model.Where("es.phone=?", phone)
	}

	var count int
	model.Count(&count)
	paginate := NewPage(page, limit, count)
	model.Offset(paginate.Offset).Limit(paginate.Limit).Scan(&res)
	return &res, &paginate
}

func (m *Partner) Cash(c *gin.Context, page int, limit int) (interface{}, *Paginator) {
	id := c.Query("id")
	var res []*struct{
		ID int `json:"id"`
		Bank string `json:"bank"`
		BankCardName string `json:"bank_card_name"`
		BankCardNo string `json:"bank_card_no"`
		Money float64 `json:"money"`
		PayTime time.Time `json:"pay_time"`
		Status int `json:"status"`
	}
	model := Table("bonus_cash").Where("target_id=?", id).Where("type=3")

	var count int
	model.Count(&count)
	paginate := NewPage(page, limit, count)
	model.Offset(paginate.Offset).Limit(paginate.Limit).Scan(&res)
	return &res, &paginate
}